home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UIterator.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  13.6 KB  |  498 lines  |  [TEXT/MPS ]

  1. // UIterator.cp 
  2. // Copyright © 1986-1991 by Apple Computer, Inc.  All rights reserved.
  3.  
  4. #ifndef __UMACAPPUTILITIES__
  5. #include <UMacAppUtilities.h>
  6. #endif
  7.  
  8. #ifndef __UOBJECT__
  9. #include <UObject.h>
  10. #endif
  11.  
  12. #ifndef __ULIST__
  13. #include <UList.h>
  14. #endif
  15.  
  16. #ifndef __UITERATOR__
  17. #include <UIterator.h>
  18. #endif
  19.  
  20.  
  21. // The CIterator methods should be defined as pure abstract methods.  However
  22. // doing so introduces a problem with determing the "key function" of the class
  23. // and leads to duplicate definitions of the VTables in all files that include
  24. // iterators.  So for the time being use empty implementations
  25.  
  26. //--------------------------------------------------------------------------------------------------
  27. #pragma segment IteratorRes
  28.  
  29. Boolean CIterator::More()
  30. {
  31.     return FALSE;
  32. }
  33.  
  34. //--------------------------------------------------------------------------------------------------
  35. #pragma segment IteratorRes
  36.  
  37. void CIterator::Reset()
  38. {
  39. }
  40.  
  41. //--------------------------------------------------------------------------------------------------
  42. #pragma segment IteratorRes
  43.  
  44. void CIterator::Advance()
  45. {
  46. }
  47.  
  48. //--------------------------------------------------------------------------------------------------
  49. #pragma segment IteratorRes
  50.  
  51. CArrayIterator* CArrayIterator::AppendToList(CArrayIterator* toList)
  52. {
  53.     if (toList)
  54.     {
  55.         fNextLink = toList->fNextLink;
  56.         fPreviousLink = toList;
  57.  
  58.         fNextLink->fPreviousLink = this;
  59.         toList->fNextLink = this;
  60.     }
  61.     return this;
  62. }
  63.  
  64. //--------------------------------------------------------------------------------------------------
  65. #pragma segment IteratorRes
  66.  
  67. CArrayIterator* CArrayIterator::RemoveFromList()
  68. {
  69.     CArrayIterator * returnLink;
  70.  
  71.     if (fNextLink == this)
  72.         returnLink = NULL;
  73.     else
  74.         returnLink = fNextLink;
  75.  
  76.     fNextLink->fPreviousLink = fPreviousLink;
  77.     fPreviousLink->fNextLink = fNextLink;
  78.  
  79.     fNextLink = this;
  80.     fPreviousLink = this;
  81.  
  82.     return returnLink;
  83. }
  84.  
  85. //--------------------------------------------------------------------------------------------------
  86. #pragma segment IteratorRes
  87.  
  88. CArrayIterator::CArrayIterator(TDynamicArray* itsDynamicArray,
  89.                                ArrayIndex itsLowBound,
  90.                                ArrayIndex itsHighBound,
  91.                                Boolean itsForward)
  92. {
  93.     if (itsDynamicArray)
  94.         IArrayIterator(itsDynamicArray, itsLowBound, itsHighBound, itsForward);
  95.     else
  96.         IArrayIterator();
  97. }
  98.  
  99. //--------------------------------------------------------------------------------------------------
  100. #pragma segment IteratorRes
  101.  
  102. CArrayIterator::CArrayIterator(TDynamicArray* itsDynamicArray,
  103.                                Boolean itsForward)
  104. {
  105.     if (itsDynamicArray)
  106.     {
  107.         ArrayIndex highBound = itsDynamicArray->GetSize();
  108.         
  109.         IArrayIterator(itsDynamicArray, Min(1, highBound), highBound, itsForward);
  110.     }
  111.     else
  112.         IArrayIterator();
  113. }
  114.  
  115. //--------------------------------------------------------------------------------------------------
  116. #pragma segment IteratorRes
  117.  
  118. CArrayIterator::CArrayIterator(TDynamicArray* itsDynamicArray)
  119. {
  120.     if (itsDynamicArray)
  121.     {
  122.         ArrayIndex highBound = itsDynamicArray->GetSize();
  123.         
  124.         IArrayIterator(itsDynamicArray, Min(1, highBound), highBound, kIterateForward);
  125.     }
  126.     else
  127.         IArrayIterator();
  128. }
  129.  
  130. //--------------------------------------------------------------------------------------------------
  131. #pragma segment IteratorRes
  132.  
  133. void CArrayIterator::IArrayIterator(TDynamicArray* itsDynamicArray,
  134.                                ArrayIndex itsLowBound,
  135.                                ArrayIndex itsHighBound,
  136.                                Boolean itsForward)
  137. {
  138.     fNextLink = this;
  139.     fPreviousLink = this;
  140.     fHighBound = MinMax(kEmptyIndex, itsHighBound, itsDynamicArray->GetSize());
  141.     fLowBound = MinMax(kEmptyIndex, itsLowBound, fHighBound);
  142.     fIterateForward = itsForward;
  143.     fDynamicArray = itsDynamicArray;
  144.  
  145.     // set the initial value of the current index based on the direction of the iteration.
  146.     if (fIterateForward)
  147.         fCurrentIndex = fLowBound;
  148.     else
  149.         fCurrentIndex = fHighBound;
  150.  
  151.     // Make sure that the fCurrentIndex counter and Iteration direction flag from
  152.     // an Iterator are used so that the fCurrentIndex counter can be "bent" if anyone
  153.     // else deletes or inserts elements while the iteration is in progress. Pretty slick, eh?
  154.  
  155.     // link me in to the list of iterations in progress
  156.     fDynamicArray->fIteratorPtr = this->AppendToList(fDynamicArray->fIteratorPtr);
  157.  
  158.     // Setup the FailInfo to catch any failures while this object is in scope
  159.     // giving control to the HandleFailure method
  160.     CatchFailures(this->fFailInfo, (CatchFailuresType) & CArrayIterator::HandleFailure, this);
  161. }
  162.  
  163. //--------------------------------------------------------------------------------------------------
  164. #pragma segment IteratorRes
  165.  
  166. void CArrayIterator::IArrayIterator()
  167. {
  168.         fNextLink = this;
  169.         fPreviousLink = this;
  170.         fHighBound = kEmptyIndex;
  171.         fLowBound = kEmptyIndex;
  172.         fCurrentIndex = kEmptyIndex;
  173.         fIterateForward = kIterateForward;
  174.         fDynamicArray = NULL;
  175. }
  176.  
  177. //--------------------------------------------------------------------------------------------------
  178. #pragma segment IteratorRes
  179.  
  180. CArrayIterator::~CArrayIterator()
  181. {
  182.     if (fDynamicArray)
  183.     {
  184.         // Remove our entry in the failure handling system as we are going out of scope
  185.         Success(fFailInfo);
  186.     
  187.         fDynamicArray->fIteratorPtr = this->RemoveFromList();
  188.     
  189.         // Check if there is a pending free request that couldn't be honored because we were
  190.         // iterating and if so… be free!
  191.         if (fDynamicArray->fFreeRequested &&!fDynamicArray->fIteratorPtr)
  192.             fDynamicArray->Free();
  193.     }
  194. }
  195.  
  196. //--------------------------------------------------------------------------------------------------
  197. #pragma segment IteratorRes
  198.  
  199. void CArrayIterator::Advance(void)
  200. {
  201.     if (fIterateForward)
  202.     {
  203.         if (fCurrentIndex < fHighBound)
  204.             ++fCurrentIndex;
  205.         else
  206.             fCurrentIndex = kEmptyIndex;
  207.     }
  208.     else
  209.     {
  210.         if (fCurrentIndex > fLowBound)
  211.             --fCurrentIndex;
  212.         else
  213.             fCurrentIndex = kEmptyIndex;
  214.     }
  215. }
  216.  
  217. //--------------------------------------------------------------------------------------------------
  218. #pragma segment IteratorRes
  219.  
  220. void CArrayIterator::DeleteElementAt(ArrayIndex theIndex,
  221.                                      ArrayIndex theCount)
  222. {
  223.     // tuck the endpoints of the iteration in to match
  224.     if (theIndex < fLowBound)
  225.         fLowBound -= theCount;
  226.  
  227.     if (theIndex <= fHighBound)
  228.         fHighBound -= theCount;
  229.  
  230.     if (fIterateForward)
  231.     {
  232.         // If the deleted element was !in the range yet to be iterated
  233.         // then bend the fCurrentIndex to account for it.
  234.         if (theIndex <= fCurrentIndex)
  235.             fCurrentIndex -= theCount;
  236.     }
  237.     else                                        // Iterating backwards 
  238.         {
  239.         // If the deleted element was IN the range yet to be iterated
  240.         // then bend the fCurrentIndex to account for it.
  241.         if (theIndex < fCurrentIndex)
  242.             fCurrentIndex -= theCount;
  243.     }
  244.  
  245.     // hand off control to the next link until you hit the last link in the circular chain
  246.     if (fNextLink != fDynamicArray->fIteratorPtr)
  247.         fNextLink->DeleteElementAt(theIndex, theCount);
  248. }
  249.  
  250. //--------------------------------------------------------------------------------------------------
  251. #pragma segment IteratorRes
  252.  
  253. void CArrayIterator::InsertElementBefore(ArrayIndex theIndex,
  254.                                          ArrayIndex theCount)
  255. {
  256.     // bump the endpoints of this iteration out to match
  257.     if (theIndex <= fLowBound)
  258.         fLowBound += theCount;
  259.  
  260.     if (theIndex <= fHighBound)
  261.         fHighBound += theCount;
  262.  
  263.     if (fIterateForward)
  264.     {
  265.         // If the inserted element was !in the range yet to be
  266.         // iterated then bend the fCurrentIndex to account for it.
  267.         if (theIndex <= fCurrentIndex)
  268.             fCurrentIndex += theCount;
  269.     }
  270.     else                                        // Iterating backward 
  271.         {
  272.         // If the inserted element was IN the range yet to be
  273.         // iterated then bend the fCurrentIndex to account for it.
  274.         if (theIndex < fCurrentIndex)
  275.             fCurrentIndex += theCount;
  276.     }
  277.  
  278.     // hand off control to the next link until you hit the last link in the circular chain
  279.     if (fNextLink != fDynamicArray->fIteratorPtr)
  280.         fNextLink->InsertElementBefore(theIndex, theCount);
  281. }
  282.  
  283. //--------------------------------------------------------------------------------------------------
  284. #pragma segment IteratorRes
  285.  
  286. pascal void CArrayIterator::HandleFailure(OSErr,
  287.                                           long)
  288. {
  289.     fDynamicArray->fIteratorPtr = this->RemoveFromList();
  290.  
  291.     // Check if there is a pending free request that couldn't be honored because we were
  292.     // iterating and if so… be free!
  293.     if (fDynamicArray->fFreeRequested &&!fDynamicArray->fIteratorPtr)
  294.         fDynamicArray->Free();
  295.  
  296.     // the error will be resignalled automatically with the pascal style of failure handler 
  297. }
  298.  
  299. //--------------------------------------------------------------------------------------------------
  300. #pragma segment IteratorRes
  301.  
  302. Boolean CArrayIterator::More(void)
  303. {
  304.     return (fCurrentIndex != kEmptyIndex);
  305. }
  306.  
  307. //--------------------------------------------------------------------------------------------------
  308. #pragma segment IteratorRes
  309.  
  310. void CArrayIterator::Reset(void)
  311. {
  312.     if (fIterateForward)
  313.         fCurrentIndex = fLowBound;
  314.     else
  315.         fCurrentIndex = fHighBound;
  316. }
  317.  
  318. //--------------------------------------------------------------------------------------------------
  319. #pragma segment IteratorRes
  320.  
  321. CObjectIterator::CObjectIterator(TSortedList* itsList,
  322.                            ArrayIndex itsLowBound,
  323.                            ArrayIndex itsHighBound,
  324.                            Boolean itsForward) :
  325.     CArrayIterator(itsList, itsLowBound, itsHighBound, itsForward)
  326. {
  327. }
  328.  
  329. //--------------------------------------------------------------------------------------------------
  330. #pragma segment IteratorRes
  331.  
  332. CObjectIterator::CObjectIterator(TSortedList* itsList,
  333.                            Boolean itsForward) :
  334.     CArrayIterator(itsList, itsForward)
  335. {
  336. }
  337.  
  338. //--------------------------------------------------------------------------------------------------
  339. #pragma segment IteratorRes
  340.  
  341. CObjectIterator::CObjectIterator(TSortedList* itsList) :
  342.     CArrayIterator(itsList)
  343. {
  344. }
  345.  
  346. //--------------------------------------------------------------------------------------------------
  347. #pragma segment IteratorRes
  348.  
  349. TObject* CObjectIterator::CurrentObject(void)
  350. {
  351.     return ((TSortedList *)fDynamicArray)->At(fCurrentIndex);
  352. }
  353.  
  354. //--------------------------------------------------------------------------------------------------
  355. #pragma segment IteratorRes
  356.  
  357. TObject* CObjectIterator::FirstObject(void)
  358. {
  359.     this->Reset();
  360.     if (this->More())
  361.         return ((TSortedList *)fDynamicArray)->At(fCurrentIndex);
  362.     else
  363.         return NULL;
  364. }
  365.  
  366. //--------------------------------------------------------------------------------------------------
  367. #pragma segment IteratorRes
  368.  
  369. TObject* CObjectIterator::NextObject(void)
  370. {
  371.     this->Advance();
  372.     if (this->More())
  373.         return ((TSortedList *)fDynamicArray)->At(fCurrentIndex);
  374.     else
  375.         return NULL;
  376. }
  377.  
  378. //--------------------------------------------------------------------------------------------------
  379. #pragma segment IteratorRes
  380.  
  381. CHandleIterator::CHandleIterator(THandleList* itsHandleList,
  382.                            ArrayIndex itsLowBound,
  383.                            ArrayIndex itsHighBound,
  384.                            Boolean itsForward) :
  385.     CArrayIterator(itsHandleList, itsLowBound, itsHighBound, itsForward)
  386. {
  387. }
  388.  
  389. //--------------------------------------------------------------------------------------------------
  390. #pragma segment IteratorRes
  391.  
  392. CHandleIterator::CHandleIterator(THandleList* itsHandleList,
  393.                            Boolean itsForward) :
  394.     CArrayIterator(itsHandleList, itsForward)
  395. {
  396. }
  397.  
  398. //--------------------------------------------------------------------------------------------------
  399. #pragma segment IteratorRes
  400.  
  401. CHandleIterator::CHandleIterator(THandleList* itsHandleList) :
  402.     CArrayIterator(itsHandleList)
  403. {
  404. }
  405.  
  406. //--------------------------------------------------------------------------------------------------
  407. #pragma segment IteratorRes
  408.  
  409. Handle CHandleIterator::CurrentHandle(void)
  410. {
  411.     return ((THandleList *)fDynamicArray)->At(fCurrentIndex);
  412. }
  413.  
  414. //--------------------------------------------------------------------------------------------------
  415. #pragma segment IteratorRes
  416.  
  417. Handle CHandleIterator::FirstHandle(void)
  418. {
  419.     this->Reset();
  420.     if (this->More())
  421.         return ((THandleList *)fDynamicArray)->At(fCurrentIndex);
  422.     else
  423.         return NULL;
  424. }
  425.  
  426. //--------------------------------------------------------------------------------------------------
  427. #pragma segment IteratorRes
  428.  
  429. Handle CHandleIterator::NextHandle(void)
  430. {
  431.     this->Advance();
  432.     if (this->More())
  433.         return ((THandleList *)fDynamicArray)->At(fCurrentIndex);
  434.     else
  435.         return NULL;
  436. }
  437.  
  438. //--------------------------------------------------------------------------------------------------
  439. #pragma segment IteratorRes
  440.  
  441. CLongintIterator::CLongintIterator(TSortedLongintList* itsSortedLongintList,
  442.                            ArrayIndex itsLowBound,
  443.                            ArrayIndex itsHighBound,
  444.                            Boolean itsForward) :
  445.     CArrayIterator(itsSortedLongintList, itsLowBound, itsHighBound, itsForward)
  446. {
  447. }
  448.  
  449. //--------------------------------------------------------------------------------------------------
  450. #pragma segment IteratorRes
  451.  
  452. CLongintIterator::CLongintIterator(TSortedLongintList* itsSortedLongintList,
  453.                            Boolean itsForward) :
  454.     CArrayIterator(itsSortedLongintList, itsForward)
  455. {
  456. }
  457.  
  458. //--------------------------------------------------------------------------------------------------
  459. #pragma segment IteratorRes
  460.  
  461. CLongintIterator::CLongintIterator(TSortedLongintList* itsSortedLongintList) :
  462.     CArrayIterator(itsSortedLongintList)
  463. {
  464. }
  465.  
  466. //--------------------------------------------------------------------------------------------------
  467. #pragma segment IteratorRes
  468.  
  469. long CLongintIterator::CurrentLong(void)
  470. {
  471.     return ((TSortedLongintList *)fDynamicArray)->At(fCurrentIndex);
  472. }
  473.  
  474. //--------------------------------------------------------------------------------------------------
  475. #pragma segment IteratorRes
  476.  
  477. long CLongintIterator::FirstLong(void)
  478. {
  479.     this->Reset();
  480.     if (this->More())
  481.         return ((TSortedLongintList *)fDynamicArray)->At(fCurrentIndex);
  482.     else
  483.         return NULL;
  484. }
  485.  
  486. //--------------------------------------------------------------------------------------------------
  487. #pragma segment IteratorRes
  488.  
  489. long CLongintIterator::NextLong(void)
  490. {
  491.     this->Advance();
  492.     if (this->More())
  493.         return ((TSortedLongintList *)fDynamicArray)->At(fCurrentIndex);
  494.     else
  495.         return NULL;
  496. }
  497.  
  498.